package com.globallogic.javatrainings.sergiiivanov.controller;

import com.globallogic.javatrainings.sergiiivanov.model.Const;
import com.globallogic.javatrainings.sergiiivanov.model.MyStack;
import com.globallogic.javatrainings.sergiiivanov.model.University;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityFailure;
import com.globallogic.javatrainings.sergiiivanov.view.GUI;

/**
 * Implements simple state machine as a default controller<br>
 * Instance of this class monitors menu navigation and keeps controllers
 * hierarchy in inner stack of {@link MyStack} <br>
 * All user interaction controllers should be based on this class and implement
 * {@link #initiate(University)}
 * 
 * @author Sergey
 * 
 */
class BasicController {
    private University university;

    private MyStack<BasicController> controllers = new MyStack<BasicController>(
            new BasicController[0]);
    private BasicController currentController;

    /**
     * General method of the controller, that executes next operation. Current
     * controller takes full control on the application at the moment.<br>
     * Main() calls currentController.initiate in the loop. Main() expects
     * instance of BasicController to be returned back and calls initiate on it,
     * giving control to returned controller.<br>
     * -Returning <b>this</b> controller keeps control over the application for
     * the next turn.<br>
     * -To give control further, controller creates new instance of
     * BasicController or subclass and returns it.<br>
     * -To return control back, controller returns <b>null</b>.<br>
     * 
     * @param u
     *            current university
     * @return <li><b>this</b> to keep control for the next turn <li>new
     *         instance of BasicController or subclass <li><b>null</b> to give
     *         control back to previous controller
     * @throws UniversityFailure
     *             when code is broken<br>
     *             <i>All cases of UniversityWarning should be caught within
     *             controller as they are not processed in Main()</i>
     */
    BasicController initiate(University u) throws UniversityFailure {
        this.university = u;
        if (currentController == null)
            currentController = new MainMenuController();
        BasicController response = currentController.initiate(this.university);
        if (response == null) {
            if (getPreviousController() == null) {
                return null;
            }
        } else if (!response.equals(currentController)) {
            saveCurrentController();
            currentController = response;
        }
        return this;
    }

    /**
     * Simple questionnaire implementation. Gets String[] of question as
     * parameter, asks user about questions and returns String[] of answers
     * 
     * @param questions
     *            String[]
     * @return String[] - answers from user on questions
     */
    static String[] questionnaire(String[] questions) {
        String[] answers = new String[questions.length];
        for (int i = 0; i < questions.length; i++) {
            GUI.getGUI().show("" + (i + 1) + "/" + questions.length + " > " + questions[i]);
            answers[i] = InputController.readString();
        }
        return answers;
    }

    boolean yes() {
        String confirmation = InputController.readString();
        return (Const.YES_YES.equalsIgnoreCase(confirmation) || Const.YES_Y.equalsIgnoreCase(confirmation));
    }

    private BasicController getPreviousController() {
        currentController = controllers.pop();
        return currentController;
    }

    private void saveCurrentController() {
        controllers.push(currentController);
    }

}
